#ifndef AVALON_SHUTTLETUPLE_HPP
#define AVALON_SHUTTLETUPLE_HPP
#include <boost/tuple/tuple.hpp>
#include "Avalon/Serialization/DataShuttle.hpp"

namespace Avalon {
namespace Serialization {

  //! Shuttles a boost::tuple.
  /*!
    \param shuttle The DataShuttle to use.
    \param value The value to shuttle.
    \param version The class version being serialized.
  */
  template<>
  struct Shuttler<boost::tuple<> > {
    void operator()(DataShuttle* shuttle, boost::tuple<>& value,
        unsigned int version) const {}
  };

  //! Shuttles a boost::tuple.
  /*!
    \param shuttle The DataShuttle to use.
    \param value The value to shuttle.
    \param version The class version being serialized.
  */
  template<typename T0>
  struct Shuttler<boost::tuple<T0> > {
    void operator()(DataShuttle* shuttle, boost::tuple<T0>& value,
        unsigned int version) const {
      shuttle->Shuttle("p0", boost::tuples::get<0>(value));
    }
  };

  //! Shuttles a boost::tuple.
  /*!
    \param shuttle The DataShuttle to use.
    \param value The value to shuttle.
    \param version The class version being serialized.
  */
  template<typename T0, typename T1>
  struct Shuttler<boost::tuple<T0, T1> > {
    void operator()(DataShuttle* shuttle, boost::tuple<T0, T1>& value,
        unsigned int version) const {
      shuttle->Shuttle("p0", boost::tuples::get<0>(value));
      shuttle->Shuttle("p1", boost::tuples::get<1>(value));
    }
  };

  //! Shuttles a boost::tuple.
  /*!
    \param shuttle The DataShuttle to use.
    \param value The value to shuttle.
    \param version The class version being serialized.
  */
  template<typename T0, typename T1, typename T2>
  struct Shuttler<boost::tuple<T0, T1, T2> > {
    void operator()(DataShuttle* shuttle, boost::tuple<T0, T1, T2>& value,
        unsigned int version) const {
      shuttle->Shuttle("p0", boost::tuples::get<0>(value));
      shuttle->Shuttle("p1", boost::tuples::get<1>(value));
      shuttle->Shuttle("p2", boost::tuples::get<2>(value));
    }
  };

  //! Shuttles a boost::tuple.
  /*!
    \param shuttle The DataShuttle to use.
    \param value The value to shuttle.
    \param version The class version being serialized.
  */
  template<typename T0, typename T1, typename T2, typename T3>
  struct Shuttler<boost::tuple<T0, T1, T2, T3> > {
    void operator()(DataShuttle* shuttle, boost::tuple<T0, T1, T2, T3>& value,
        unsigned int version) const {
      shuttle->Shuttle("p0", boost::tuples::get<0>(value));
      shuttle->Shuttle("p1", boost::tuples::get<1>(value));
      shuttle->Shuttle("p2", boost::tuples::get<2>(value));
      shuttle->Shuttle("p3", boost::tuples::get<3>(value));
    }
  };

  //! Shuttles a boost::tuple.
  /*!
    \param shuttle The DataShuttle to use.
    \param value The value to shuttle.
    \param version The class version being serialized.
  */
  template<typename T0, typename T1, typename T2, typename T3, typename T4>
  struct Shuttler<boost::tuple<T0, T1, T2, T3, T4> > {
    void operator()(DataShuttle* shuttle,
        boost::tuple<T0, T1, T2, T3, T4>& value, unsigned int version) const {
      shuttle->Shuttle("p0", boost::tuples::get<0>(value));
      shuttle->Shuttle("p1", boost::tuples::get<1>(value));
      shuttle->Shuttle("p2", boost::tuples::get<2>(value));
      shuttle->Shuttle("p3", boost::tuples::get<3>(value));
      shuttle->Shuttle("p4", boost::tuples::get<4>(value));
    }
  };

  //! Shuttles a boost::tuple.
  /*!
    \param shuttle The DataShuttle to use.
    \param value The value to shuttle.
    \param version The class version being serialized.
  */
  template<typename T0, typename T1, typename T2, typename T3, typename T4,
    typename T5>
  struct Shuttler<boost::tuple<T0, T1, T2, T3, T4, T5> > {
    void operator()(DataShuttle* shuttle,
        boost::tuple<T0, T1, T2, T3, T4, T5>& value,
        unsigned int version) const {
      shuttle->Shuttle("p0", boost::tuples::get<0>(value));
      shuttle->Shuttle("p1", boost::tuples::get<1>(value));
      shuttle->Shuttle("p2", boost::tuples::get<2>(value));
      shuttle->Shuttle("p3", boost::tuples::get<3>(value));
      shuttle->Shuttle("p4", boost::tuples::get<4>(value));
      shuttle->Shuttle("p5", boost::tuples::get<5>(value));
    }
  };

  //! Shuttles a boost::tuple.
  /*!
    \param shuttle The DataShuttle to use.
    \param value The value to shuttle.
    \param version The class version being serialized.
  */
  template<typename T0, typename T1, typename T2, typename T3, typename T4,
    typename T5, typename T6>
  struct Shuttler<boost::tuple<T0, T1, T2, T3, T4, T5, T6> > {
    void operator()(DataShuttle* shuttle,
        boost::tuple<T0, T1, T2, T3, T4, T5, T6>& value,
        unsigned int version) const {
      shuttle->Shuttle("p0", boost::tuples::get<0>(value));
      shuttle->Shuttle("p1", boost::tuples::get<1>(value));
      shuttle->Shuttle("p2", boost::tuples::get<2>(value));
      shuttle->Shuttle("p3", boost::tuples::get<3>(value));
      shuttle->Shuttle("p4", boost::tuples::get<4>(value));
      shuttle->Shuttle("p5", boost::tuples::get<5>(value));
      shuttle->Shuttle("p6", boost::tuples::get<6>(value));
    }
  };

  //! Shuttles a boost::tuple.
  /*!
    \param shuttle The DataShuttle to use.
    \param value The value to shuttle.
    \param version The class version being serialized.
  */
  template<typename T0, typename T1, typename T2, typename T3, typename T4,
    typename T5, typename T6, typename T7>
  struct Shuttler<boost::tuple<T0, T1, T2, T3, T4, T5, T6, T7> > {
    void operator()(DataShuttle* shuttle,
        boost::tuple<T0, T1, T2, T3, T4, T5, T6, T7>& value,
        unsigned int version) const {
      shuttle->Shuttle("p0", boost::tuples::get<0>(value));
      shuttle->Shuttle("p1", boost::tuples::get<1>(value));
      shuttle->Shuttle("p2", boost::tuples::get<2>(value));
      shuttle->Shuttle("p3", boost::tuples::get<3>(value));
      shuttle->Shuttle("p4", boost::tuples::get<4>(value));
      shuttle->Shuttle("p5", boost::tuples::get<5>(value));
      shuttle->Shuttle("p6", boost::tuples::get<6>(value));
      shuttle->Shuttle("p7", boost::tuples::get<7>(value));
    }
  };

  //! Shuttles a boost::tuple.
  /*!
    \param shuttle The DataShuttle to use.
    \param value The value to shuttle.
    \param version The class version being serialized.
  */
  template<typename T0, typename T1, typename T2, typename T3, typename T4,
    typename T5, typename T6, typename T7, typename T8>
  struct Shuttler<boost::tuple<T0, T1, T2, T3, T4, T5, T6, T7, T8> > {
    void operator()(DataShuttle* shuttle,
        boost::tuple<T0, T1, T2, T3, T4, T5, T6, T7, T8>& value,
        unsigned int version) const {
      shuttle->Shuttle("p0", boost::tuples::get<0>(value));
      shuttle->Shuttle("p1", boost::tuples::get<1>(value));
      shuttle->Shuttle("p2", boost::tuples::get<2>(value));
      shuttle->Shuttle("p3", boost::tuples::get<3>(value));
      shuttle->Shuttle("p4", boost::tuples::get<4>(value));
      shuttle->Shuttle("p5", boost::tuples::get<5>(value));
      shuttle->Shuttle("p6", boost::tuples::get<6>(value));
      shuttle->Shuttle("p7", boost::tuples::get<7>(value));
      shuttle->Shuttle("p8", boost::tuples::get<8>(value));
    }
  };

  //! Shuttles a boost::tuple.
  /*!
    \param shuttle The DataShuttle to use.
    \param value The value to shuttle.
    \param version The class version being serialized.
  */
  template<typename T0, typename T1, typename T2, typename T3, typename T4,
    typename T5, typename T6, typename T7, typename T8, typename T9>
  struct Shuttler<boost::tuple<T0, T1, T2, T3, T4, T5, T6, T7, T8, T9> > {
    void operator()(DataShuttle* shuttle,
        boost::tuple<T0, T1, T2, T3, T4, T5, T6, T7, T8, T9>& value,
        unsigned int version) const {
      shuttle->Shuttle("p0", boost::tuples::get<0>(value));
      shuttle->Shuttle("p1", boost::tuples::get<1>(value));
      shuttle->Shuttle("p2", boost::tuples::get<2>(value));
      shuttle->Shuttle("p3", boost::tuples::get<3>(value));
      shuttle->Shuttle("p4", boost::tuples::get<4>(value));
      shuttle->Shuttle("p5", boost::tuples::get<5>(value));
      shuttle->Shuttle("p6", boost::tuples::get<6>(value));
      shuttle->Shuttle("p7", boost::tuples::get<7>(value));
      shuttle->Shuttle("p8", boost::tuples::get<8>(value));
      shuttle->Shuttle("p9", boost::tuples::get<9>(value));
    }
  };
}
}

#endif // AVALON_SHUTTLETUPLE_HPP
